package io.hellsinger.vortex

import android.app.Activity
import android.content.ComponentName
import android.content.Intent
import android.content.ServiceConnection
import android.os.Bundle
import android.os.IBinder
import android.view.Gravity
import android.view.ViewGroup.LayoutParams.WRAP_CONTENT
import android.widget.FrameLayout
import android.widget.FrameLayout.LayoutParams.MATCH_PARENT
import android.window.OnBackInvokedDispatcher.PRIORITY_DEFAULT
import androidx.core.graphics.ColorUtils
import androidx.core.view.WindowCompat
import androidx.core.view.WindowCompat.getInsetsController
import androidx.core.view.WindowInsetsCompat
import io.hellsinger.navigation.route.DefaultAndroidRouter
import io.hellsinger.navigation.route.RouteMapper
import io.hellsinger.navigation.screen.HostNavPopupView
import io.hellsinger.navigation.screen.HostNavScreenView
import io.hellsinger.navigation.screen.ScreenController
import io.hellsinger.theme.Colors
import io.hellsinger.theme.vortex.VortexSettings
import io.hellsinger.vortex.foundation.isAtLeastAndroid13
import io.hellsinger.vortex.navigation.GlobalUiProvider
import io.hellsinger.vortex.navigation.ServiceProvider
import io.hellsinger.vortex.navigation.findDependencies
import io.hellsinger.vortex.service.VortexService
import io.hellsinger.vortex.service.VortexServiceBinder
import io.hellsinger.vortex.service.di.ServiceDependencies
import io.hellsinger.vortex.ui.component.drawable.NavigationIconDrawable
import io.hellsinger.vortex.ui.component.item.menu.MenuActionListener
import io.hellsinger.vortex.ui.component.navigation.NavigationBarView
import io.hellsinger.vortex.ui.component.observeInsets
import io.hellsinger.vortex.ui.component.updatePadding
import io.hellsinger.vortex.ui.dsl.frame
import io.hellsinger.vortex.ui.dsl.frameParams
import io.hellsinger.vortex.ui.dsl.params
import io.hellsinger.vortex.ui.navigation.Routes
import io.hellsinger.vortex.ui.screen.BottomDrawerNavigationScreenController
import io.hellsinger.vortex.ui.screen.storage.create.StorageCreateItemScreenController
import io.hellsinger.vortex.ui.screen.storage.detail.StorageItemDetailScreenController
import io.hellsinger.vortex.ui.screen.storage.editor.StorageFileEditorScreenController
import io.hellsinger.vortex.ui.screen.storage.list.StorageListScreenController
import io.hellsinger.vortex.ui.screen.storage.rename.StorageRenameItemScreenController
import io.hellsinger.vortex.ui.screen.storage.schedule.StorageOperationScheduleScreenController
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.launch

class MainActivity :
    Activity(),
    MenuActionListener,
    ServiceConnection,
    RouteMapper<ScreenController<*>?>,
    GlobalUiProvider,
    ServiceProvider<VortexServiceBinder?> {
    private val service = MutableStateFlow<VortexServiceBinder?>(null)
    private var router: DefaultAndroidRouter? = null

    override var root: FrameLayout? = null
        private set
    private var navContainer: HostNavScreenView? = null
    override var bar: NavigationBarView? = null
        private set
    private var popup: HostNavPopupView? = null

    override fun onMapRoute(route: String): ScreenController<*>? =
        when (route) {
            Routes.Storage.MAIN -> StorageListScreenController(context = this)
            Routes.Storage.CREATE -> StorageCreateItemScreenController(context = this)
            Routes.Storage.ITEM_DETAIL -> StorageItemDetailScreenController(context = this)
            Routes.Storage.RENAME -> StorageRenameItemScreenController(context = this)
            Routes.Storage.FILE_EDITOR -> StorageFileEditorScreenController(context = this)
            Routes.Storage.SCHEDULE -> StorageOperationScheduleScreenController(context = this)
            else -> null
        }

    override fun getService(): Flow<VortexServiceBinder?> = this.service

    override fun onCreate(inState: Bundle?) {
        super.onCreate(inState)
        bindService(
            Intent(this, VortexService::class.java),
            this,
            BIND_AUTO_CREATE,
        )

        WindowCompat.setDecorFitsSystemWindows(window, false)

        if (ColorUtils.calculateLuminance((VortexSettings.colors { key_navigation_bar_surface_color })) > 0.5) {
            with(getInsetsController(window, window.decorView)) {
                isAppearanceLightNavigationBars = true
                isAppearanceLightStatusBars = true
            }
        } else {
            with(getInsetsController(window, window.decorView)) {
                isAppearanceLightNavigationBars = false
                isAppearanceLightStatusBars = false
            }
        }

        window.statusBarColor = Colors.Transparent
        window.navigationBarColor = Colors.Transparent

        root =
            frame(this) {
                params(MATCH_PARENT, MATCH_PARENT)
                navContainer =
                    HostNavScreenView(context).apply {
                        frameParams(MATCH_PARENT, MATCH_PARENT)
                        this@frame.addView(this, 0)
                    }

                bar =
                    NavigationBarView(context).apply {
                        setBackgroundColor(VortexSettings.colors { key_navigation_bar_surface_color })
                        setTitleColor(VortexSettings.colors { key_navigation_bar_title_color })
                        setSubtitleColor(VortexSettings.colors { key_navigation_bar_subtitle_color })
                        setIconsColor(VortexSettings.colors { key_navigation_bar_icon_color })
                        setIconsRippleColor(VortexSettings.colors { key_navigation_bar_icon_ripple_color })
                        frameParams(MATCH_PARENT, WRAP_CONTENT) {
                            gravity = Gravity.BOTTOM
                        }
                        this@frame.addView(this, 1)
                        observeInsets { view, insets ->
                            val i = WindowInsetsCompat.toWindowInsetsCompat(insets)
                            val pb = i.getInsets(WindowInsetsCompat.Type.navigationBars()).bottom
                            updatePadding(bottom = pb)
                            insets
                        }
                        setNavigationClickListener {
                            if (router?.canNavigateBack() == true) {
                                router?.navigateBack()
                            } else {
                                router?.navigate(BottomDrawerNavigationScreenController(this@MainActivity))
                            }
                        }
                    }

                popup =
                    HostNavPopupView(context).apply {
                    }
            }

        setContentView(root)

        router =
            DefaultAndroidRouter(
                mapper = this@MainActivity,
                container = navContainer!!,
                popup = popup!!,
            ) { index ->
                if (index > 0) {
                } else {
                    bar?.animateIconTo(NavigationIconDrawable.Type.CLOSE)
                }
            }

        if (inState != null) {
            router?.restore(buffer = inState)
        } else {
            router?.init(route = Routes.Storage.MAIN)
        }

        if (isAtLeastAndroid13) {
            onBackInvokedDispatcher.registerOnBackInvokedCallback(PRIORITY_DEFAULT) { onBackPressed() }
        }

//        val intent = createVortexServiceIntent()
//
//        if (isAtLeastAndroid8) {
//            startForegroundService(intent)
//        } else {
//            startService(intent)
//        }
    }

    override fun onServiceConnected(
        name: ComponentName?,
        service: IBinder?,
    ) {
        CoroutineScope(findDependencies<ServiceDependencies>().dispatchers.immediate).launch {
            this@MainActivity.service.emit(service as VortexServiceBinder?)
        }
    }

    override fun onServiceDisconnected(name: ComponentName?) {
        CoroutineScope(findDependencies<ServiceDependencies>().dispatchers.immediate).launch {
            service.emit(null)
        }
    }

    override fun onBackPressed() {
        onBackInvoked()
    }

    override fun onSaveInstanceState(outState: Bundle) {
//        super.onSaveInstanceState(outState)
        router?.save(outState)
    }

    private fun onBackInvoked() {
        if (router?.onBackInvoked() == false) {
            super.onBackPressed()
        }
    }

    override fun onMenuActionCall(id: Int): Boolean =
        when (id) {
            else -> false
        }

    override fun onActivityResult(
        requestCode: Int,
        resultCode: Int,
        data: Intent?,
    ) {
        if (router?.onActivityResult(requestCode, resultCode, data) == false) {
            super.onActivityResult(requestCode, resultCode, data)
        }
    }

    override fun onRequestPermissionsResult(
        requestCode: Int,
        permissions: Array<out String>,
        grantResults: IntArray,
    ) {
    }

    override fun onDestroy() {
        unbindService(this)
        stopService(createVortexServiceIntent())
        super.onDestroy()
    }
}

private fun MainActivity.createVortexServiceIntent(action: String? = null): Intent =
    Intent(applicationContext, VortexService::class.java).apply {
        this.action = action
    }
